#include "mythread.h"
#include <QDebug>

MyThread::MyThread(std::string ad, int p, bool* c) : running(true), x(0)
{
    _client = new Client(ad, p, p+1, c);

    if(_client->isConnectedMain && _client->isConnectedGame)
    { message = "<font color=\"red\">--- Connecte au serveur ---</font>"; }
    else
    { message = "<font color=\"red\">--- Deconnecte du serveur ---</font>"; }
}

MyThread::~MyThread()
{
    delete _client;
}

void MyThread::run()
{
    while (running)
    {
        if(_client->_selector.wait(sf::milliseconds(60)))
        {
            sf::Packet p;
            if(_client->_selector.isReady(_client->_sockMainServ))
            {
                _client->recv(p, true);
                traitementMain(p);
            }
            if(_client->_selector.isReady(_client->_sockGameServ))
            {
                _client->recv(p, false);
                traitementGame(p);
            }
        }
    }
}

void MyThread::traitementMain(sf::Packet & p)
{
    int x;
    p >> x;

    if (DEBUG) {std::cout << "Packet recu (main) --- evenement " << x << std::endl;}

    switch(x)
    {
        case eMAIN_NEWCLIENT :
            receptionClient();
            break;

        case eMAIN_NEWGAME :
            receptionPartie();
            break;

        case eMAIN_NEWMSG :
            receptionMessage();
            break;

        case eMAIN_DECOCLIENT :
            decoClient();
            break;

        case eMAIN_DECOGAME :
            decoPartie();
            break;

        case eMAIN_ALLCLIENTS :
        {
            sf::Packet p2;
            _client->recv(p2, true);
            int nbClients;
            p2 >> nbClients;

            for (int i(0); i < nbClients; i++)
            {
                receptionClient();
            }
        } break;

        case eMAIN_ALLGAMES :
        {
            sf::Packet p2;
            _client->recv(p2, true);
            int nbGames;
            p2 >> nbGames;
            for (int i(0); i < nbGames; i++)
            {
                receptionPartie();
            }
        } break;

        case eJOIN_GAME :
        {
            traitementJoinGame();
        } break;

        case eCREATE_GAME :
        {
            traitementNllePartie();
        } break;

        case eMAIN_ADDPARTIE :
        {
            traitementAddPartie();
        } break;

        case eMAIN_RMPARTIE :
        {
            traitementRmPartie();
        } break;

        default :
            if (DEBUG) {std::cout << "case default du switch main du thread --- evenement " << x << std::endl;}
            break;
    }
}

void MyThread::traitementGame(sf::Packet & p)
{
    int x;
    p >> x;

    if (DEBUG) {std::cout << "Packet recu (game) --- evenement " << x << std::endl;}

    switch(x)
    {
        case eMAIN_NEWMSG :
            receptionMessageGame();
            break;

        case eLAUNCH :
        {
            receptionCarte();
        } break;

        case eMAIN_NEWCLSALON :
        {
            traitementNewClSalon();
        } break;

        case eMAIN_DELCLSALON :
        {
            traitementDelClSalon();
        } break;

        case eMAIN_ALLCLIENTGAME :
        {
            sf::Packet p2;
            _client->recv(p2, false);
            int nbClients;
            p2 >> nbClients;

            for (int i(0); i < nbClients; i++)
            {
                traitementNewClSalon();
            }
        } break;

        case eMAIN_QUIT :
        {
            traitementSalQuit();
        } break;

        case eGAME_ETAT :
        {
            traitementGameEtat();
        } break;

        case eGAME_SELECTION :
        {
            traitementSelectionT();
        } break;

        case eGAME_TMAJ :
        {
            traitementTMaj();
        } break;

        case eGAME_WIN :
        {
            traitementWin();
        } break;

        default :
            if (DEBUG) {std::cout << "case default du switch game du thread --- evenement " << x << std::endl;}
            break;
    }
}

void MyThread::receptionClient()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomClient;
    emit newClient(QString(nomClient.c_str()));
}

void MyThread::receptionPartie()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomPartie >> nbJAct >> nbJMax;
    emit newGame(QString(nomPartie.c_str()), (int)nbJAct, (int)nbJMax);
}

void MyThread::receptionMessage()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> message;
    if (message == "Lancement de partie")
    {
        message = "<font color=\"red\">" + message + "</font>";
    }
    else if (x%2 == 1)
    {
        message = "<font color=\"grey\">" + message + "</grey>";
    }

    x++;

    emit newMsg(QString(message.c_str()));
}

void MyThread::receptionMessageGame()
{
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> message;
    emit newMsg(QString(message.c_str()));
}

void MyThread::decoClient()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomClient;
    emit decoC(QString(nomClient.c_str()));
}

void MyThread::decoPartie()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomPartie;
    emit decoP(QString(nomPartie.c_str()));
}

void MyThread::receptionCarte()
{
    sf::Uint8 nbJ, nbTparJ, nbCentres;
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> nbJ >> nbTparJ;

    emit datasGame((int)nbJ, (int)nbTparJ);

    p2.clear();
    _client->recv(p2, false);
    p2 >> nbCentres;

    for (int i(0); i < nbCentres; i++)
    {
        sf::Packet p3;
        _client->recv(p3, false);

        sf::Uint8 x, y;
        p3 >> x >> y;
        emit addPoint((int)x, (int)y);
    }

    p2.clear();
    _client->recv(p2, false);
    sf::Uint8 idCamp;
    p2 >> idCamp;
    emit idJoueur((int)idCamp);

    p2.clear();
    _client->recv(p2, false);
    sf::Uint8 etatJ;
    p2 >> etatJ;
    emit changeEtat((int)etatJ);

    emit launch();
}

void MyThread::traitementJoinGame()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> valeurPartie;

    emit joinGame((int)valeurPartie);
}

void MyThread::traitementNllePartie()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> valeurPartie;

    emit createGame((int)valeurPartie);
}

void MyThread::traitementAddPartie()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomPartie;
    emit addPartie(QString(nomPartie.c_str()));
}

void MyThread::traitementRmPartie()
{
    sf::Packet p2;
    _client->recv(p2, true);
    p2 >> nomPartie;
    emit rmPartie(QString(nomPartie.c_str()));
}

void MyThread::traitementNewClSalon()
{
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> nomClient;
    emit newClientSalon(QString(nomClient.c_str()));
}

void MyThread::traitementDelClSalon()
{
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> nomClient;
    emit delClientSalon(QString(nomClient.c_str()));
}

void MyThread::traitementSalQuit()
{
    emit salQuit();
}

void MyThread::traitementGameEtat()
{
    sf::Packet p2;
    _client->recv(p2, false);
    sf::Uint8 x;
    p2 >> x;

    if (DEBUG) {std::cout << "---> traitementGameEtat() : nouvel etat : " << (int)x << std::endl;}

    emit changeEtat((int)x);
}

void MyThread::traitementSelectionT()
{
    sf::Packet p2;
    _client->recv(p2, false);
    sf::Int8 x, y;
    p2 >> x >> y;

    if (DEBUG) {std::cout << "---> traitementSelectionT() : x=" << (int)x << " - y=" << (int)y << std::endl;}

    emit selectionT((int)x, (int)y);
}

void MyThread::traitementTMaj()
{
    sf::Int8 numT;
    sf::Uint8 nbDes, numC, debut;
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> numT >> nbDes >> numC >> debut;

    if (DEBUG) {std::cout << "---> traitementTMaj() : numT=" << (int)numT << " - nbDes=" << (int)nbDes << " - numC=" << (int)numC << " - debut=" << (int)debut << std::endl;}

    emit tmaj((int)numT, (int)nbDes, (int)numC, (int)debut);
}

void MyThread::traitementWin()
{
    std::string pseudo;
    sf::Packet p2;
    _client->recv(p2, false);
    p2 >> pseudo;

    if (DEBUG) {std::cout << "---> vainqueur : " << pseudo << std::endl;}

    emit win(QString(pseudo.c_str()));
}

void MyThread::quitter()
{
    running = false;
}

std::string MyThread::getNomClient()
{
    return nomClient;
}

std::string MyThread::getNomPartie()
{
    return nomPartie;
}

std::string MyThread::getMessage()
{
    return message;
}

sf::Uint8 MyThread::getNbJAct()
{
    return nbJAct;
}

sf::Uint8 MyThread::getNbJMax()
{
    return nbJMax;
}

Client* MyThread::getClient()
{
    return _client;
}

sf::Uint8 MyThread::getValeurPartie()
{
    return valeurPartie;
}
